//
// Created by LU on 2022/10/21.
//

#include "Inifile.h"
#include <sstream>
// 文件标准库
#include <fstream>
#include <iostream>
#include <stdlib.h>

Value::Value() {

}

Value::Value(bool value) {
//    if (value)
//    {
//        m_value = "true";
//    }
//    else
//    {
//        m_value = "false";
//    }
//    m_value = value ? "true" : "false";

    *this = value;
}
Value::Value(int value) {
    *this = value;
}
Value::Value(double value) {
    *this = value;
}
Value::Value(const char * value) {
    *this = value;
}
Value::Value(const string & value) {
    *this = value;
}
//Value::Value(const string &value) :m_value(value) {
//
//}


Value & Value::operator = (bool value) {
    m_value = value ? "true" : "false";
    //return *this返回的是当前对象的克隆或者本身
    return *this;
}
Value & Value::operator = (int value) {
    stringstream ss;
    ss << value;
    m_value = ss.str();
    return *this;
}
Value & Value::operator = (double value) {
    stringstream ss;
    ss << value;
    m_value = ss.str();
    return *this;
}
Value & Value::operator = (const char * value) {
    m_value = value;
    return *this;
}
Value & Value::operator = (const string & value) {
    m_value = value;
    return *this;
}


Value::operator bool()
{
//    if (m_value == "true")
//    {
//        return true;
//    }
//    else
//    {
//        return false;
//    }
    return m_value == "true";
}
Value::operator int()
{
    // “atof”用于将字符串转换为浮点值，但函数不会报告转换错误；考虑改用“strtod”
//    return std::atoi(m_value.c_str());
    char* end;
    return std::strtol(m_value.c_str(), &end, 10);
}
Value::operator double()
{
    //return std::atof(m_value.c_str());
    char* end;
    return std::strtod(m_value.c_str(),&end);
}
Value::operator string()
{
    return m_value;
}

IniFile::IniFile() = default;

IniFile::IniFile(const string & filename)
{
    load(filename);
}

IniFile::~IniFile() = default;

bool IniFile::load(const string &filename) {
    m_filename = filename;
    ifstream  fin(filename);
    if (fin.fail())
    {
        std::cout << "open file error" << std::endl;
        return false;
    }
    string line;
    string section;
    while (std::getline(fin, line))
    {
        if (line.empty())
        {
            continue;
        }
        if (line[0] == '#') // it's comment
        {
            continue;
        }
        if (line[0] == '[')
        {
            // 获取段名称  server 字符
            int pos = line.find_first_of(']');
            if (pos < 0)
            {
                return false;
            }
            section = line.substr(1, pos-1);
            section = trim(section);
            m_sections[section] = Section();
        }
        else
        {
            int pos = line.find_first_of('=');
            if (pos < 0)
            {
                return false;
            }
            string key = line.substr(0, pos);
            key = trim(key);
            string value = line.substr(pos + 1 ,line.length()-pos);
            value = trim(value);
//            std::cout << value << std::endl;
            m_sections[section][key] = value;
        }
//        std::cout << line << std::endl;
    }
    fin.close();
//    int port ;
//    port = get("server", "port");
//    std::cout << port << std::endl;
//    std::cout << 11 << std::endl;
    return true;
}
// 去除字符串左右的空格  换行字符
string IniFile::trim(string s) {
    if(s.empty())
    {
        return s;
    }
    s.erase(0, s.find_first_not_of(" \n\r"));
    s.erase(s.find_last_not_of(" \n\r")+1);
    return s;
}

Value & IniFile::get(const string &section, const string &key) {
    return m_sections[section][key];
}


void IniFile::set(const string & section, const string &key, const Value & value)
{
    m_sections[section][key] = value;
}
bool IniFile::has(const string & section, const string &key){
    // 判断 section 是否存在
    auto it= m_sections.find(section);
    if (it != m_sections.end())
    {
        return (it->second.find(key) != it ->second.end());
    }
    return false;
}

bool IniFile::has(const string & section)
{
    return (m_sections.find(section) != m_sections.end());
}

void IniFile::remove(const string & section, const string & key)
{
//    std::map<string, Section>::iterator it= m_sections.find(section);
    auto it= m_sections.find(section);
    if (it != m_sections.end())
    {
        it->second.erase(key);
    }
}
void IniFile::remove(const string & section)
{
    m_sections.erase(section);
}
void IniFile::clear()
{
    m_sections.clear();
}

string IniFile::str()
{
    stringstream ss;
    for (auto & m_section : m_sections)
    {
        ss << "[" << m_section.first  << "]" << std::endl;
        for (auto & iter : m_section.second)
        {
            ss << iter.first << " = " << string(iter.second) << std::endl;
        }
        ss << endl;
    }
    return ss.str();
}

void IniFile::show()
{
//    for (std::map<string, Section>::iterator it = m_sections.begin();
//            it != m_sections.end();
//            it++)
//    {
//        std::cout << "[" << it->first  << "]" << std::endl;
//        for (std::map<string, Value>::iterator iter = it->second.begin();iter !=it->second.end();++iter)
//        {
//            std::cout << iter->first << " = " << string(iter->second) << std::endl;
//        }
//        std::cout << std::endl;
//    }
    std::cout << str();
}


bool IniFile::save(const string & filename)
{
    ofstream fout(filename.c_str());
    if (fout.fail())
    {
        std::cout << " read fail" << std::endl;
        return false;
    }
    fout << str();
//    fout.flush();
    fout.close();
    return true;
}
